package com.tcl.plugin

import com.android.build.api.transform.DirectoryInput
import com.android.build.api.transform.Format
import com.android.build.api.transform.JarInput
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInput
import com.android.build.api.transform.TransformInvocation
import com.android.build.api.transform.TransformOutputProvider
import com.android.build.gradle.internal.pipeline.TransformManager
import com.android.utils.FileUtils
import org.apache.commons.codec.digest.DigestUtils
import org.apache.commons.io.IOUtils
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter

/**
 * 自定义的 Transform 类
 */
class CustomTransform extends Transform {

    //自定义 Task 名称
    @Override
    String getName() {
        return this.getClass().name
    }

    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }

    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }

    // 当前Transform是否支持增量编译
    @Override
    boolean isIncremental() {
        return false
    }

    @Override
    void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
        super.transform(transformInvocation)
        TransformOutputProvider outputProvider = transformInvocation.getOutputProvider()
        //清理文件
        outputProvider.deleteAll();

        transformInvocation.getInputs().each {
            TransformInput input ->
                //这里存放着开发者手写的类
                input.directoryInputs.each {
                    DirectoryInput directoryInput ->
                        File dir = directoryInput.file
                        println("dir==="+dir)
                        dir.eachFileRecurse {
                            File file ->
                                def name = file.name
                                if(name.endsWith(".class") && !name.startsWith("R\$") &&
                                !"R.class".equalsIgnoreCase(name) && !"BuildConfig.class".equalsIgnoreCase(name)){
                                    println("name==="+name)
                                    //class阅读器
                                    ClassReader cr = new ClassReader(file.bytes);
                                    //写出器
                                    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                                    //分析，处理结果写入cw
                                    cr.accept(new ClassAdapterVisitor(cw),ClassReader.EXPAND_FRAMES)
                                    byte[] newClassBytes = cw.toByteArray();
                                    FileOutputStream fos = new FileOutputStream(file.parentFile.absolutePath+File.separator+name)
                                    fos.write(newClassBytes)
                                    fos.close()
                                }
                        }

                        //获取output目录，处理完输入文件之后，要把输出给下一个任务
                        def  dest = outputProvider.getContentLocation(directoryInput.name,directoryInput.contentTypes,
                        directoryInput.scopes,Format.DIRECTORY)
                        //将input的目录复制到output指定目录
                        FileUtils.copyDirectory(directoryInput.file,dest)
                }

                //遍历jar文件，对jar不操作，但是要输出到out路径
                input.jarInputs.each {
                    JarInput jarInput ->
                        String destName = jarInput.file.name
                        String absolutePath = jarInput.file.absolutePath
                        println("jar = ${absolutePath}")
                        if(absolutePath.endsWith(".jar")){
                            //...对jar进行插入字节码
                        }

                        // 重命名输出文件（同目录copyFile会冲突）
                        def md5Name = DigestUtils.md5(absolutePath)
                        if (destName.endsWith(".jar")) {
                            destName = destName.substring(0, destName.length() - 4)
                        }

                        //def modifyJar = ModifyUtils.modifyJar(jarInput.file, transformInvocation.context.getTemporaryDir())
                        def modifyJar = null
                        if (modifyJar == null) {
                            modifyJar = jarInput.file
                        }

                        //获取输出文件
                        File dest =outputProvider.getContentLocation(destName+"_"+md5Name,
                                        jarInput.contentTypes, jarInput.scopes, Format.JAR)
                        //中间可以将 jarInput.file 进行操作！
                        //copy 到输出目录
                        FileUtils.copyFile(modifyJar, dest)
                }
        }
    }

    /**
     * 修改目录里的 class
     * @param dir
     * @param classFile
     * @param tempDir
     * @return
     */
    private static File modifyClassFile(File dir, File classFile, File tempDir) {
        File modified = null
        try {
            println "dir.absolutePath + File.separator: ${dir.absolutePath + File.separator}"
            String className = path2ClassName(classFile.absolutePath.replace(dir.absolutePath + File.separator, ""))
            println "className: $className"
            byte[] sourceClassBytes = IOUtils.toByteArray(new FileInputStream(classFile))
            /*byte[] modifyClassBytes = ModifyUtils.modifyClasses(sourceClassBytes)
            if (modifyClassBytes) {
                modified = new File(tempDir, className.replace('.', '') + '.class')
                if (modified.exists()) {
                    modified.delete()
                }
                modified.createNewFile()
                new FileOutputStream(modified).write(modifyClassBytes)
            }*/
        } catch (Exception e) {
            e.printStackTrace()
        }
        return modified
    }
    private static String path2ClassName(String pathName) {
        pathName.replace(File.separator, ".").replace(".class", "")
    }
}